package com.michael.demos.ddd.springboot.domains;

import lombok.NonNull;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 一个窗口的账户活动
 */
public class ActivityWindow {

    /**
     * 此窗口内的帐户活动列表
     */
    private List<Activity> activities;

    /**
     * 第一个活动的时间戳
     */
    public LocalDateTime getStartTimestamp() {
        return activities.stream()
                         .min(Comparator.comparing(Activity::getTimestamp))
                         .orElseThrow(IllegalStateException::new)
                         .getTimestamp();
    }

    /**
     * 最后一个活动的时间戳
     */
    public LocalDateTime getEndTimestamp() {
        return activities.stream()
                         .max(Comparator.comparing(Activity::getTimestamp))
                         .orElseThrow(IllegalStateException::new)
                         .getTimestamp();
    }

    /**
     * 通过汇总此窗口中所有活动的值来计算余额
     */
    public Money calculateBalance(Account.AccountId accountId) {
        Money depositBalance = activities.stream()
                                         .filter(a -> a.getTargetAccountId().equals(accountId))
                                         .map(Activity::getMoney)
                                         .reduce(Money.ZERO, Money::add);

        Money withdrawalBalance = activities.stream()
                                            .filter(a -> a.getSourceAccountId().equals(accountId))
                                            .map(Activity::getMoney)
                                            .reduce(Money.ZERO, Money::add);

        return Money.add(depositBalance, withdrawalBalance.negate());
    }

    public ActivityWindow(@NonNull List<Activity> activities) {
        this.activities = activities;
    }

    public ActivityWindow(@NonNull Activity... activities) {
        this.activities = new ArrayList<>(Arrays.asList(activities));
    }

    public List<Activity> getActivities() {
        return Collections.unmodifiableList(this.activities);
    }

    public void addActivity(Activity activity) {
        this.activities.add(activity);
    }
}
